/*
 * Copyright 2013-2019 Xia Jun(3979434@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************************************
 *                                                                                     *
 *                        Website : http://www.farsunset.com                           *
 *                                                                                     *
 ***************************************************************************************
 */
package com.workcell.workdata.im.mvc.interceptor;

import com.workcell.workdata.im.constant.Common;
import com.workcell.workdata.im.model.response.ResponseEntity;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * 用于打印接口请求日志,
 * 如果不需要打印，可以删除该类即可
 */
@ControllerAdvice
public class LogcatInterceptor implements ResponseBodyAdvice<ResponseEntity<Object>> {

	private final Logger logger = LoggerFactory.getLogger(LogcatInterceptor.class);

	@Override
	public boolean supports(MethodParameter parameter, Class aClass) {
		Class<?> valueClass =  parameter.getParameterType();
		return ResponseEntity.class.isAssignableFrom(valueClass);
	}


	@Override
	public ResponseEntity<Object> beforeBodyWrite(ResponseEntity<Object> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

		HttpServletRequest httpRequest = ((ServletServerHttpRequest) request).getServletRequest();

		if (httpRequest instanceof ContentCachingRequestWrapper){

			String requestLog = getRequestLog((ContentCachingRequestWrapper) httpRequest);

			logger.info("\n{}",requestLog);
		}

		return body;
	}


	private String getRequestLog(ContentCachingRequestWrapper wrapper){

		HttpServletRequest servletRequest = (HttpServletRequest) wrapper.getRequest();

		StringBuilder builder = new StringBuilder();
		builder.append(String.format("%s %s HTTP/1.1 %n",servletRequest.getMethod(), servletRequest.getRequestURI()));

		String headerFormat = "[header]%s: %s%n";

		builder.append(String.format(headerFormat, Common.MVC_HEADER_TOKEN, servletRequest.getHeader(Common.MVC_HEADER_TOKEN)));
		builder.append(String.format(headerFormat, Common.MVC_HEADER_APP_TYPE, servletRequest.getHeader(Common.MVC_HEADER_APP_TYPE)));
		builder.append(String.format(headerFormat, Common.MVC_HEADER_APP_VERSION, servletRequest.getHeader(Common.MVC_HEADER_APP_VERSION)));
		builder.append(String.format(headerFormat, HttpHeaders.ACCEPT_LANGUAGE, servletRequest.getHeader(HttpHeaders.ACCEPT_LANGUAGE)));
		builder.append(String.format(headerFormat, HttpHeaders.ORIGIN, servletRequest.getHeader(HttpHeaders.ORIGIN)));
		builder.append(String.format(headerFormat, HttpHeaders.USER_AGENT, servletRequest.getHeader(HttpHeaders.USER_AGENT)));
		builder.append(String.format(headerFormat, HttpHeaders.CONTENT_TYPE, servletRequest.getHeader(HttpHeaders.CONTENT_TYPE)));

		for (Map.Entry<String,String[]> params :servletRequest.getParameterMap().entrySet()){
			builder.append(String.format("[parameter]%s: %s%n", params.getKey(),StringUtils.join(params.getValue(),",")));
		}

		String contentType = servletRequest.getHeader(HttpHeaders.CONTENT_TYPE);

		if (MediaType.APPLICATION_JSON_VALUE.equals(contentType)){
			String body = StringUtils.toEncodedString(wrapper.getContentAsByteArray(),Charset.forName(wrapper.getCharacterEncoding()));
			builder.append(String.format("[body]%n%s%n",body));
		}

		return builder.toString();
	}

}
